﻿Imports System.IO
Imports System.IO.IsolatedStorage
Imports System.Net.Http
Imports System.Text
Imports System.Threading
Imports System.Threading.Tasks
Imports LSW.WP7.Extension

Namespace Utility
    Public Enum Problem
        Ok
        Cancelled
        Other
    End Enum
    Public Module WebHelper
        Dim cts As New CancellationTokenSource

        Public Async Function GetHtml(url As String) As Task(Of String)
            Return Await DownloadString(New Uri(url))
        End Function

        Public Async Function DownloadString(url As Uri) As Task(Of String)
            Dim tcs As New TaskCompletionSource(Of String)
            Dim wc As New WebClient
            AddHandler wc.DownloadStringCompleted, Sub(s, e)
                                                       If e.Error IsNot Nothing Then
                                                           tcs.SetException(e.Error)
                                                       ElseIf e.Cancelled Then
                                                           tcs.TrySetCanceled()
                                                       Else
                                                           tcs.TrySetResult(e.Result)
                                                       End If
                                                   End Sub
            wc.DownloadStringAsync(url)
            Return Await tcs.Task
        End Function

        Public Async Function DownloadFile(url As Uri) As Task(Of Stream)
            Dim tcs As New TaskCompletionSource(Of Stream)
            Dim wc As New WebClient
            AddHandler wc.OpenReadCompleted, Sub(s, e)
                                                 If e.Error IsNot Nothing Then
                                                     tcs.SetException(e.Error)
                                                 ElseIf e.Cancelled Then
                                                     tcs.TrySetCanceled()
                                                 Else
                                                     tcs.TrySetResult(e.Result)
                                                 End If
                                             End Sub
            wc.OpenReadAsync(url)
            Return Await tcs.Task
        End Function

        Public Async Function DownloadFileFromWeb(url As Uri, filename As String) As Task(Of Problem)
            Return Await DownloadFileFromWeb(url, filename, New CancellationToken)
        End Function

        Public Async Function DownloadFileFromWeb(url As Uri, filename As String, cToken As CancellationToken) As Task(Of Problem)
            Try
                Using s = Await DownloadFile(url)
                    Using isf = IsolatedStorageFile.GetUserStoreForApplication
                        If isf.FileExists(filename) Then isf.DeleteFile(filename)
                        Using file = isf.CreateFile(filename)
                            Const BUFFER_SIZE = 1024
                            Dim buf(BUFFER_SIZE - 1) As Byte

                            Dim bytesread = 0
                            While bytesread.InlineAssignHelper(Await s.ReadAsync(buf, 0, BUFFER_SIZE)) > 0
                                cToken.ThrowIfCancellationRequested()
                                file.Write(buf, 0, bytesread)
                            End While
                        End Using
                    End Using
                End Using
                Return Problem.Ok
            Catch ex As Exception
                If TypeOf ex Is OperationCanceledException Then
                    Return Problem.Cancelled
                Else
                    Return Problem.Other
                End If
            End Try
        End Function

        Public Async Function PostToWebApi(url As String, postdata As String) As Task(Of String)
            Return Await Post(url, postdata, "application/json")
        End Function

        Public Async Function Post(url As String, postdata As String, mediatype As String) As Task(Of String)
            Dim tcs As New TaskCompletionSource(Of String)
            Dim wc As New HttpClient

            Dim httpResponse = Await wc.PostAsync(url, New StringContent(postdata, Encoding.UTF8, mediatype))
            httpResponse.EnsureSuccessStatusCode()

            Return Await httpResponse.Content.ReadAsStringAsync
        End Function

        Public Async Function Post(url As String, postdata As Dictionary(Of String, String)) As Task(Of String)
            Dim param = String.Empty

            For i As Integer = 0 To postdata.Count - 1
                param &= postdata.Keys(i) & "=" & postdata.Values(i)
                If i <> postdata.Count - 1 Then
                    param &= "&"
                End If
            Next

            Return Await Post(url, param, Nothing)
        End Function
    End Module
End Namespace